<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>

</body>
<script>
    // 【1】定义
    // 函数记忆是指将上次的计算结果缓存起来，当下次调用时，如果遇到相同的参数，就直接返回缓存中的数据。
    // 举个例子：
    function add(a, b) {
        return a + b;
    }
    // 假设 memoize 可以实现函数记忆
    var memoizedAdd = memoize(add);
    memoizedAdd(1, 2) // 3
    memoizedAdd(1, 2); // 相同的参数，第二次调用时，从缓存中取出数据，而非重新计算一次
    // 【2】原理
    // 实现这样一个 memoize 函数很简单， 原理上只用把参数和对应的结果数据存到一个对象中，
    //  调用时， 判断参数对应的数据是否存在， 存在就返回对应的结果数据。

    // 【3】 第一版： 我们来写一版、
    // 第一版 (来自《JavaScript权威指南》)
    function memoize(f) {
        var cache = {};
        return function() {
            //形参长度  +  在 
            debugger
            var key = arguments.length + Array.prototype.join.call(arguments, ",");
            if (key in cache) {
                return cache[key]
            } else {
                return cache[key] = f.apply(this, arguments)
            }
        }
    }
    // 我们来测试一下：

    var add = function(a, b, c) {
        return a + b + c
    };
    //将函数作为参数放入记忆函数
    var memoizedAdd = memoize(add);
    console.log(memoizedAdd);
    console.time('use memoize')

    //将函数作为参数放入记忆函数
    for (var i = 0; i < 100000; i++) {
        memoizedAdd(1, 2, 3)
    }
    console.timeEnd('use memoize')

    console.time('not use memoize')
    for (var i = 0; i < 100000; i++) {
        add(1, 2, 3)
    }
    console.timeEnd('not use memoize');
    // 在 Chrome 中， 使用 memoize 大约耗时 60 ms， 如果我们不使用函数记忆， 大约耗时 1.3 ms 左右。

    // 【4】注意
    // 什么，我们使用了看似高大上的函数记忆，结果却更加耗时，这个例子近乎有 60 倍呢！
    // 所以，函数记忆也并不是万能的，你看这个简单的场景，其实并不适合用函数记忆。
    // 需要注意的是，函数记忆只是一种编程技巧，本质上是牺牲算法的空间复杂度以换取更优的时间复杂度，
    // 在客户端 JavaScript 中代码的执行时间复杂度往往成为瓶颈，因此在大多数场景下，
    // 这种牺牲空间换取时间的做法以提升程序执行效率的做法是非常可取的。
</script>

</html>